package com.wd.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;

import org.apache.log4j.helpers.LogLog;

/**
 * @date : 2012-9-26, 17:54:43
 * @author: long
 * @email :108232706
 * @qq.com
 * @description: NioSocketAcceptor类
 */
public class NioSocketAcceptor {

	private Selector selector = null;
	private ServerSocketChannel serverChannel = null;
	private boolean isStarted;
	private boolean isInit;

	public NioSocketAcceptor() throws IOException {
		synchronized (this) {
			selector = Selector.open(); // 静态方法 实例化selector
			serverChannel = ServerSocketChannel.open();
			// 采用两个线程，提高服务器对并发的响应速度，负责接受的设置成阻塞
			// serverChannel.configureBlocking(false); // 设置为非阻塞方式,如果为true
			// 那么就为传统的阻塞方式
			// serverChannel.socket().setReuseAddress(true);
		}
	}

	public boolean start(int port) {
		synchronized (this) {

			if (!isStarted()) {
				if (!isInit) {
					if (!init(port)) {
						return false;
					}
					isInit = true;
				}
				if (!serverChannel.isOpen()) {
					try {
						serverChannel.open();
					} catch (IOException e) {
						e.printStackTrace();
						return false;
					}
				}
				// 端口
				// 采用两个线程，提高服务器对并发的响应速度，负责接受的设置成阻塞,不需要监听器
				// serverChannel.register(selector,
				// SelectionKey.OP_ACCEPT);//
				// 注册
				// OP_ACCEPT事件
				setStarted(true);
			}

			return true;
		}
	}

	private boolean init(int port) {
		try {
			serverChannel.socket().bind(new InetSocketAddress(port)); // 绑定IP 及
			isInit = true;
		} catch (IOException e) {
			LogLog.error(String.format("[NioSocketAcceptor]绑定端口%s失败,%s!",port,e));
			return false;
		}
		return true;
	}

	/** {@inheritDoc} */
	protected void destroy() throws Exception {
		synchronized (this) {
			if (selector != null) {
				selector.close();
			}
		}
	}

	public boolean stop() {
		synchronized (this) {
			if (isStarted()) {
				SelectionKey key = getServerChannel().keyFor(selector);
				if (key != null) {
					key.cancel();
				}
				try {
					destroy();
					getServerChannel().close();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
				setStarted(false);
			}
			return true;
		}
	}

	/** {@inheritDoc} */
	protected void wakeup() {
		selector.wakeup();
	}

	public Selector getSelector() {
		return selector;
	}

	public void setSelector(Selector selector) {
		this.selector = selector;
	}

	public ServerSocketChannel getServerChannel() {
		synchronized (this) {
			return this.serverChannel;
		}
	}

	public void setServerChannel(ServerSocketChannel serverChannel) {
		this.serverChannel = serverChannel;
	}

	public boolean isStarted() {
		return isStarted;
	}

	public void setStarted(boolean isStarted) {
		this.isStarted = isStarted;
	}
}
